home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / SmallTalk / mstcint.c < prev    next >
C/C++ Source or Header  |  1995-08-25  |  25KB  |  1,103 lines

  1. /***********************************************************************
  2.  *
  3.  *    C - Smalltalk Interface module
  4.  *
  5.  ***********************************************************************/
  6.  
  7. /***********************************************************************
  8.  *
  9.  * Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  10.  * Written by Steve Byrne.
  11.  *
  12.  * This file is part of GNU Smalltalk.
  13.  *
  14.  * GNU Smalltalk is free software; you can redistribute it and/or modify it
  15.  * under the terms of the GNU General Public License as published by the Free
  16.  * Software Foundation; either version 1, or (at your option) any later 
  17.  * version.
  18.  * 
  19.  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  20.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  21.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  22.  * more details.
  23.  * 
  24.  * You should have received a copy of the GNU General Public License along with
  25.  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  26.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  27.  *
  28.  ***********************************************************************/
  29.  
  30.  
  31. /*
  32.  *    Change Log
  33.  * ============================================================================
  34.  * Author      Date       Change 
  35.  * sbb         23 Feb 92      Added support for reading and writing scalar types.
  36.  *
  37.  * sbb         19 Jul 91      Started adding support for the DLD package.
  38.  *
  39.  * sbb         22 Jan 91      Added putenv().
  40.  *
  41.  * sbb         17 Nov 90      Added support for UnixStream primitives.
  42.  *
  43.  * sbb         11 Aug 90      Added knowledge of byteArrayOut type.
  44.  *
  45.  * sbyrne     4 Jun 89      Added Smalltalk data conversion type.
  46.  *
  47.  * sbyrne    29 May 89      Created.
  48.  *
  49.  */
  50.  
  51. /* Define this to enable initialization of the SunView hacks in the
  52.    ./examples directory */
  53. /* #define SUN_WIN_HACKS */
  54.  
  55. #include "mst.h"
  56. #include "mstinterp.h"
  57. #include "mstdict.h"
  58. #include "mstoop.h"
  59. #include "mstsym.h"
  60. #include "mstcallin.h"
  61.  
  62. #define ARG_VEC_SIZE        20 /* 20 ints, 10 longs or ptrs, 5 dbls */
  63.  
  64.  
  65. typedef enum {
  66.   intAlign,
  67.   longAlign,
  68.   ptrAlign,
  69.   doubleAlign
  70. } AlignmentType;
  71.  
  72. typedef enum {            /* types for C parameters */
  73.   unknownType,            /* when there is no type a priori */
  74.   charType,
  75.   stringType,
  76.   stringOutType,        /* for things that modify string params */
  77.   symbolType,
  78.   byteArrayType,
  79.   byteArrayOutType,
  80.   intType,
  81.   longType,
  82.   doubleType,
  83.   voidType,            /* valid only as a return type */
  84.   variadicType,            /* for parameters, this param is an array
  85.                    to be interpreted as arguments.  Note that
  86.                    only simple conversions are performed in
  87.                    this case. */
  88.   cObjectType,            /* a C object is being passed */
  89.   smalltalkType            /* no conversion to-from C...C sees this
  90.                    as "void *".  */
  91. } CDataType;
  92.  
  93. typedef struct CFuncDescriptorStruct {
  94.   OBJ_HEADER;
  95.   OOP        cFunction;
  96.   OOP        cFunctionName;
  97.   OOP        returnType;
  98.   OOP        numFixedArgs;
  99.   OOP        argTypes[1];    /* variable length, really numFixedArgs long */
  100. } *CFuncDescriptor;
  101.  
  102. typedef struct SymbolTypeMapStruct {
  103.   OOP        *symbol;
  104.   CDataType    type;
  105. } SymbolTypeMap;
  106.  
  107. typedef struct StringInfoStruct {
  108.   Byte        *cString;
  109.   OOP        stringOOP;
  110.   CDataType    returnedType;
  111. } StringInfo;
  112.  
  113. typedef union CParamUnionUnion {
  114.   int        intVal;
  115.   long        longVal;
  116.   voidPtr    ptrVal;
  117.   double    doubleVal;
  118.   int        valueVec[sizeof(double) / sizeof(int)];
  119. } CParamUnion;
  120.  
  121. typedef struct     CFuncInfoStruct {
  122.   char        *funcName;
  123.   void        (*funcAddr)();
  124. } CFuncInfo;
  125.  
  126. extern int            errno;
  127.  
  128. void                defineCFunc();
  129.  
  130. static void             pushObj(), callCFunction(),
  131.                 badType(), pushSmalltalkObj();
  132. static CDataType         getCType();
  133. static CFuncDescriptor         getCFuncDescriptor();
  134. static OOP            classifyTypeSymbol();
  135. static int            savedErrno;
  136.  
  137. static OOP            readChar();
  138. static OOP            readUChar();
  139. static OOP            readShort();
  140. static OOP            readUShort();
  141. static OOP            readLong();
  142. static OOP            readULong();
  143. static OOP            readFloat();
  144. static OOP            readDouble();
  145.  
  146. static void            writeChar();
  147. static void            writeShort();
  148. static void            writeLong();
  149. static void            writeFloat();
  150. static void            writeDouble();
  151.  
  152. static CFuncInfo        cFuncInfo[100], *cFuncIndex = cFuncInfo;
  153. static int            cArgVec[ARG_VEC_SIZE];
  154. static int            *cArg;
  155. static StringInfo        stringInfo[ARG_VEC_SIZE], *sip;
  156. /* printable names for corresponding C types */
  157. static char            *cTypeName[] = {
  158.   "void?",            /* unknownType */
  159.   "char",            /* charType */
  160.   "char *",            /* stringType */
  161.   "char *",            /* stringOutType */
  162.   "char *",            /* symbolType */
  163.   "char *",            /* byteArrayType */
  164.   "char *",            /* byteArrayOutType */
  165.   "int",            /* intType */
  166.   "long",            /* longType */
  167.   "double",            /* doubleType */
  168.   "void?",            /* voidType */
  169.   "var args?",            /* variadicType */
  170.   "void *",            /* cObjectType */
  171.   "void *",            /* smalltalkType */
  172. };
  173.  
  174. static SymbolTypeMap    symbolTypeMap[] = {
  175.   &unknownSymbol, unknownType,
  176.   &charSymbol, charType,
  177.   &stringSymbol, stringType,
  178.   &stringOutSymbol, stringOutType,
  179.   &symbolSymbol, symbolType,
  180.   &byteArraySymbol, byteArrayType,
  181.   &byteArrayOutSymbol, byteArrayOutType,
  182.   &intSymbol, intType,
  183.   &longSymbol, longType,
  184.   &doubleSymbol, doubleType,
  185.   &voidSymbol, voidType,
  186.   &variadicSymbol, variadicType,
  187.   &cObjectSymbol, cObjectType,
  188.   &smalltalkSymbol, smalltalkType,
  189.   nil, unknownType
  190. };
  191.  
  192. /* the arg vec pointer must be = 0 mod alignments[align] */
  193. /* This is quite likely to be machine dependent.  Currently it is set up
  194.  * to work correctly on sun2's, sun3's and sun4's */
  195. static int         alignments[] = {
  196.   sizeof(int),            /* intType */
  197.   sizeof(long),            /* longType */
  198.   sizeof(voidPtr),        /* ptrType */
  199.   DOUBLE_ALIGNMENT        /* doubleType */
  200. };
  201.  
  202. static int        typeSizes[] = {
  203.   sizeof(int),            /* intType */
  204.   sizeof(long),            /* longType */
  205.   sizeof(voidPtr),        /* ptrType */
  206.   sizeof(double)        /* doubleType */
  207. };
  208.  
  209. /*
  210.  *    void marli(n)
  211.  *
  212.  * Description
  213.  *
  214.  *    Test/example C function.
  215.  *
  216.  * Inputs
  217.  *
  218.  *    n     : number of times to emit message.
  219.  *
  220.  */
  221. void marli(n)
  222. int n;
  223. {
  224.   int        i;
  225.  
  226.   for (i = 0; i < n; i++) {
  227.     printf("Marli loves Steve!!!\n");
  228.   }
  229. }
  230.  
  231. static int getErrno()
  232. {
  233.   return (savedErrno);
  234. }
  235.  
  236.  
  237.  
  238. #ifdef debugging /* Wed Nov 14 12:34:44 1990 */
  239. /**/myioctl(fd, request, arg)
  240. /**/int    fd, request;
  241. /**/char    *arg;
  242. /**/{
  243. /**/  printf("fd %d request %x arg %x\n", fd, request, arg);
  244. /**/  return (ioctl(fd, request, arg));
  245. /**/}
  246. #endif /* debugging Wed Nov 14 12:34:44 1990 */
  247.  
  248. /*
  249.  *    static int my_putenv(str)
  250.  *
  251.  * Description
  252.  *
  253.  *    Does a putenv library call.  Exists because putenv (at least Sun's)
  254.  *    expects that the string passed in will exist for the duration, and
  255.  *    Smalltalk will free the string it passed to this this routine when
  256.  *    control returns to it.
  257.  *
  258.  * Inputs
  259.  *
  260.  *    str   : String to stuff into the environment.  Of the form name=value.
  261.  *
  262.  * Outputs
  263.  *
  264.  *    Returned value from putenv() call.
  265.  */
  266. static int my_putenv(str)
  267. char    *str;
  268. {
  269.   char        *clone;
  270.   int        len;
  271.  
  272.   len = strlen(str) + 1;    /* hold the null */
  273.   clone = (char *)malloc(len);
  274.   strcpy(clone, str);
  275.   return (putenv(clone));
  276. }
  277.  
  278.  
  279. static void testCallin(oop)
  280. OOP    oop;
  281. {
  282.   strMsgSend(oop, "inspect", nil);
  283. #ifdef preserved /* Tue Dec 31 21:55:47 1991 */
  284. /**/  OOP        o, sel;
  285. /**/  double    f;
  286. /**/
  287. /**/  sel = symbolToOOP("printNl");
  288. /**/  o = msgSend(stringToOOP(msg), sel, nil);
  289. /**/  strMsgSend(o, "inspect", nil);
  290. /**/  strMsgSend(strMsgSend(o, ",", o, nil), "printNl", nil);
  291. /**/  msgSendf(nil, "%s %s printNl", "this is a test");
  292. /**/  msgSendf(&f, "%f %i + %f", 3, 4.7);
  293. /**/  printf("result = %f\n", f);
  294. #endif /* preserved Tue Dec 31 21:55:47 1991 */
  295. }
  296.  
  297. void initCFuncs()
  298. {
  299.   extern void marli(), windowLoop();
  300.   extern char *getAttrName();
  301.   extern voidPtr *getAttrValue();
  302.   extern void window_create();
  303.   extern int system();
  304.   extern char *getenv();
  305.   extern int read(), write(), open(), close(), ioctl(), lseek()/*, tell()*/;
  306.  
  307.   defineCFunc("system", system);
  308.   defineCFunc("getenv", getenv);
  309.   defineCFunc("putenv", my_putenv);
  310.  
  311.   defineCFunc("open", open);
  312.   defineCFunc("close", close);
  313.   defineCFunc("read", read);
  314.   defineCFunc("write", write);
  315.   /* defineCFunc("ioctl", myioctl); */
  316.   defineCFunc("ioctl", ioctl);
  317.   defineCFunc("lseek", lseek);
  318. /*  defineCFunc("tell", tell);*/
  319.  
  320.   /* just to round out the set */
  321.   defineCFunc("readChar", readChar);
  322.   defineCFunc("readUChar", readUChar);
  323.   defineCFunc("readShort", readShort);
  324.   defineCFunc("readUShort", readUShort);
  325.   defineCFunc("readLong", readLong);
  326.   defineCFunc("readULong", readULong);
  327.   defineCFunc("readFloat", readFloat);
  328.   defineCFunc("readDouble", readDouble);
  329.  
  330.   defineCFunc("writeChar", writeChar);
  331.   defineCFunc("writeShort", writeShort);
  332.   defineCFunc("writeLong", writeLong);
  333.   defineCFunc("writeFloat", writeFloat);
  334.   defineCFunc("writeDouble", writeDouble);
  335.  
  336.   defineCFunc("getErrno", getErrno);
  337.  
  338.   defineCFunc("testCallin", testCallin);
  339.  
  340. #ifdef DLD
  341.   initDldLib();
  342. #endif
  343.  
  344.   /* Non standard routines */
  345.  
  346.   defineCFunc("marli", marli);
  347. #ifdef SUN_WIN_HACKS
  348.   defineWindowFuncs();
  349. #endif /* SUN_WIN_HACKS */
  350.  
  351. #ifdef notdefined
  352.   defineCFunc("getAttrName", getAttrName);
  353.   defineCFunc("getAttrValue", getAttrValue);
  354. #endif
  355. }
  356.  
  357. static OOP readChar(fd)
  358. int    fd;
  359. {
  360.   char        c;
  361.  
  362.   if (read(fd, &c, sizeof(c)) != sizeof(c)) {
  363.     return (nilOOP);
  364.   }
  365.  
  366.   return (charOOPAt(c));
  367. }
  368.  
  369. static OOP readUChar(fd)
  370. int    fd;
  371. {
  372.   unsigned char    c;
  373.  
  374.   if (read(fd, &c, sizeof(c)) != sizeof(c)) {
  375.     return (nilOOP);
  376.   }
  377.  
  378.   return (charOOPAt(c));
  379. }
  380.  
  381. static OOP readShort(fd)
  382. int    fd;
  383. {
  384.   short        s;
  385.  
  386.   if (read(fd, &s, sizeof(s)) != sizeof(s)) {
  387.     return (nilOOP);
  388.   }
  389.  
  390.   return (fromInt(s));
  391. }
  392.  
  393. static OOP readUShort(fd)
  394. int    fd;
  395. {
  396.   unsigned short s;
  397.  
  398.   if (read(fd, &s, sizeof(s)) != sizeof(s)) {
  399.     return (nilOOP);
  400.   }
  401.  
  402.   return (fromInt(s));
  403. }
  404.  
  405. static OOP readLong(fd)
  406. int    fd;
  407. {
  408.   long        l;
  409.  
  410.   if (read(fd, &l, sizeof(l)) != sizeof(l)) {
  411.     return (nilOOP);
  412.   }
  413.  
  414.   return (fromInt(l));
  415. }
  416.  
  417. static OOP readULong(fd)
  418. int    fd;
  419. {
  420.   unsigned long l;
  421.  
  422.   if (read(fd, &l, sizeof(l)) != sizeof(l)) {
  423.     return (nilOOP);
  424.   }
  425.  
  426.   return (fromInt(l));
  427. }
  428.  
  429. static OOP readFloat(fd)
  430. int    fd;
  431. {
  432.   float     f;
  433.  
  434.   if (read(fd, &f, sizeof(f)) != sizeof(f)) {
  435.     return (nilOOP);
  436.   }
  437.  
  438.   return (floatNew(f));
  439. }
  440.  
  441. static OOP readDouble(fd)
  442. int    fd;
  443. {
  444.   double     d;
  445.  
  446.   if (read(fd, &d, sizeof(d)) != sizeof(d)) {
  447.     return (nilOOP);
  448.   }
  449.  
  450.   return (floatNew(d));
  451. }
  452.  
  453. static void writeChar(fd, c)
  454. int    fd;
  455. char    c;
  456. {
  457.   write(fd, &c, sizeof(c));
  458. }
  459.  
  460. static void writeShort(fd, s)
  461. int    fd;
  462. short    s;
  463. {
  464.   write(fd, &s, sizeof(s));
  465. }
  466.  
  467. static void writeLong(fd, l)
  468. int    fd;
  469. long    l;
  470. {
  471.   write(fd, &l, sizeof(l));
  472. }
  473.  
  474. static void writeFloat(fd, f)
  475. int    fd;
  476. float    f;
  477. {
  478.   write(fd, &f, sizeof(f));
  479. }
  480.  
  481. static void writeDouble(fd, d)
  482. int    fd;
  483. double    d;
  484. {
  485.   write(fd, &d, sizeof(d));
  486. }
  487.  
  488.  
  489. #ifdef DLD
  490.  
  491. /***********************************************************************
  492.  *
  493.  *    GNU Dynamic Linking support code
  494.  *
  495.  ***********************************************************************/
  496.  
  497. #include <dld.h>
  498.  
  499. char    *dldArgv0;
  500.  
  501. static int getUndefinedSymCount()
  502. {
  503.   return (dld_undefined_sym_count);
  504. }
  505.  
  506.  
  507. initDldLib()
  508. {
  509.   if (dld_init (dld_find_executable (dldArgv0)) == 0) {
  510.     defineCFunc("dldLink", dld_link);
  511.     defineCFunc("dldUnlinkByFile", dld_unlink_by_file);
  512.     defineCFunc("dldUnlinkBySymbol", dld_unlink_by_symbol);
  513.     defineCFunc("dldGetSymbol", dld_get_symbol);
  514.     defineCFunc("dldGetFunc", dld_get_func);
  515.     defineCFunc("dldFunctionExecutableP", dld_function_executable_p);
  516.     defineCFunc("dldListUndefinedSym", dld_list_undefined_sym);
  517.     defineCFunc("dldCreateReference", dld_create_reference);
  518.     defineCFunc("dldDefineSym", dld_define_sym);
  519.     defineCFunc("dldRemoveDefinedSymbol", dld_remove_defined_symbol);
  520.  
  521.     defineCFunc("getUndefinedSymCount", getUndefinedSymCount);
  522.  
  523.     /* so user level code can invoke it! */
  524.     defineCFunc("defineCFunc", defineCFunc);
  525.   }
  526. }
  527.  
  528. #endif
  529.  
  530.  
  531. void defineCFunc(funcName, funcAddr)
  532. char    *funcName;
  533. void    (*funcAddr)();
  534. {
  535.   cFuncIndex->funcName = funcName;
  536.   cFuncIndex->funcAddr = funcAddr;
  537.   cFuncIndex++;
  538. }
  539.  
  540. void (*lookupFunction(funcName))()
  541. char    *funcName;
  542. {
  543.   CFuncInfo    *fip;
  544.  
  545.   for (fip = cFuncInfo; fip < cFuncIndex; fip++) {
  546.     if (strcmp(funcName, fip->funcName) == 0) {
  547.       return (fip->funcAddr);
  548.     }
  549.   }
  550.   return (nil);
  551. }
  552.  
  553.  
  554.  
  555. /*
  556.  *    void invokeCRoutine(numArgs, methodOOP)
  557.  *
  558.  * Description
  559.  *
  560.  *    Invokes a C routine.  The Smalltalk arguments have been popped off the
  561.  *    Smalltalk stack when this routine returns.
  562.  *
  563.  * Inputs
  564.  *
  565.  *    numArgs: 
  566.  *        
  567.  *    methodOOP: 
  568.  *        
  569.  *
  570.  */
  571. void invokeCRoutine(numArgs, methodOOP)
  572. long    numArgs;
  573. OOP    methodOOP;
  574. {
  575.   CFuncDescriptor desc;
  576.   CDataType    cType;
  577.   OOP        oop; /* oopArgVec[32]; */
  578.   int        i;
  579.  
  580.   cArg = cArgVec;
  581.   
  582.   desc = getCFuncDescriptor(methodOOP);
  583.  
  584.   sip = stringInfo;
  585.  
  586.   for (i = 0; i < numArgs; i++) {
  587.     oop = stackAt(numArgs - i - 1);
  588.     cType = getCType(desc, i);
  589.     pushSmalltalkObj(oop, cType);
  590.   }
  591.  
  592.   popNOOPs(numArgs);
  593.  
  594.   callCFunction(desc);
  595.  
  596.   /* Fixup all returned string variables */
  597.   for ( ; sip-- != stringInfo; ) {
  598.     if (sip->returnedType == stringOutType) {
  599.       setOOPString(sip->stringOOP, sip->cString);
  600.     } else if (sip->returnedType == byteArrayOutType) {
  601.       setOOPBytes(sip->stringOOP, sip->cString);
  602.     }
  603.     free(sip->cString);
  604.   }
  605. }
  606.  
  607. static CFuncDescriptor getCFuncDescriptor(methodOOP)
  608. OOP    methodOOP;
  609. {
  610.   OOP        associationOOP, descOOP;
  611.  
  612.   associationOOP = methodLiteralExt(methodOOP, 0);
  613.   descOOP = associationValue(associationOOP);
  614.   return ((CFuncDescriptor)oopToObj(descOOP));
  615. }
  616.  
  617. static CDataType getCType(desc, index)
  618. CFuncDescriptor desc;
  619. int    index;
  620. {
  621.   if (index < toInt(desc->numFixedArgs)) {
  622.     return ((CDataType)toInt(desc->argTypes[index]));
  623.   } else {
  624.     return (unknownType);
  625.   }
  626. }
  627.  
  628. static void pushSmalltalkObj(oop, cType)
  629. OOP    oop;
  630. CDataType cType;
  631. {
  632.   OOP        class;
  633.   int        i;
  634.   CParamUnion    u;
  635.  
  636.   if (cArg - cArgVec >= ARG_VEC_SIZE) {
  637.     errorf("Attempt to push more than %d ints; extra parameters ignored",
  638.        ARG_VEC_SIZE);
  639.     return;
  640.   }
  641.  
  642.   if (isInt(oop)) {
  643.     class = integerClass;
  644.   } else if (oop == trueOOP || oop == falseOOP) {
  645.     class = booleanClass;
  646.   } else {
  647.     class = oopClass(oop);
  648.   }
  649.  
  650.   if (cType == smalltalkType) {
  651.     u.ptrVal = (voidPtr)oop;
  652.     registerOOP(oop);        /* make sure it doesn't get gc'd */
  653.     pushObj(&u, ptrAlign);
  654.   } else if (class == integerClass) {
  655.     if (cType == longType || cType == unknownType) {
  656.       u.longVal = toInt(oop);
  657.       pushObj(&u, longAlign);
  658.     } else if (cType == intType || cType == charType) {
  659.       u.intVal = toInt(oop);
  660.       pushObj(&u, intAlign);
  661.     } else {
  662.       badType("Integer", cType);
  663.     }
  664.   } else if (class == booleanClass) {
  665.     if (cType == intType || cType == charType || cType == unknownType) {
  666.       u.intVal = (oop == trueOOP);
  667.       pushObj(&u, intAlign);
  668.     } else if (cType == longType) {
  669.       u.longVal = (oop == trueOOP);
  670.       pushObj(&u, longAlign);
  671.     } else {
  672.       badType("Boolean", cType);
  673.     }
  674.   } else if (class == charClass) {
  675.     if (cType == charType || cType == unknownType) {
  676.       u.intVal = charOOPValue(oop);
  677.       pushObj(&u, intAlign);
  678.     } else {
  679.       badType("Character", cType);
  680.     }
  681.   } else if (class == stringClass) {
  682.     if (cType == stringType || cType == stringOutType
  683.     || cType == unknownType) {
  684.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  685.     errorf("Too many string arguments, max is %d.  Extra ignored",
  686.            ARG_VEC_SIZE);
  687.       }
  688.       sip->cString = toCString(oop);
  689.       u.ptrVal = (voidPtr)sip->cString;
  690.       sip->stringOOP = oop;
  691.       sip->returnedType = cType;
  692.       sip++;
  693.       pushObj(&u, ptrAlign);
  694.     } else {
  695.       badType("String", cType);
  696.     }
  697.   } else if (class == symbolClass) {
  698.     if (cType == symbolType || cType == stringType || cType == unknownType) {
  699.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  700.     errorf("Too many string arguments, max is %d.  Extra ignored",
  701.            ARG_VEC_SIZE);
  702.       }
  703.       sip->cString = toCString(oop);
  704.       u.ptrVal = (voidPtr)sip->cString;
  705.       sip->stringOOP = oop;
  706.       sip->returnedType = cType;
  707.       sip++;
  708.       pushObj(&u, ptrAlign);
  709.     } else {
  710.       badType("Symbol", cType);
  711.     }
  712.   } else if (class == byteArrayClass) {
  713.     if (cType == byteArrayType || cType == byteArrayOutType
  714.     || cType == unknownType) {
  715.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  716.     errorf("Too many string arguments, max is %d.  Extra ignored",
  717.            ARG_VEC_SIZE);
  718.       }
  719.       sip->cString = toByteArray(oop);
  720.       u.ptrVal = (voidPtr)sip->cString;
  721.       sip->stringOOP = oop;
  722.       sip->returnedType = cType;
  723.       sip++;
  724.       pushObj(&u, ptrAlign);
  725.     } else {
  726.       badType("ByteArray", cType);
  727.     }
  728.   } else if (class == floatClass) {
  729.     if (cType == doubleType || cType == unknownType) {
  730.       u.doubleVal = floatOOPValue(oop);
  731.       pushObj(&u, doubleAlign);
  732.     } else {
  733.       badType("Float", cType);
  734.     }
  735.   } else if (class == cObjectClass) { 
  736.     if (cType == cObjectType || cType == unknownType) {
  737.       u.ptrVal = cObjectValue(oop);
  738.       pushObj(&u, ptrAlign);
  739.     } else {
  740.       badType("CObject", cType);
  741.     }
  742.   } else if ((cType == cObjectType || cType == unknownType)
  743.          && isAKindOf(class, cObjectClass)) {
  744.     u.ptrVal = cObjectValue(oop);
  745.     pushObj(&u, ptrAlign);
  746.   } else if (class == undefinedObjectClass) { /* how to encode nil */
  747.     switch (cType) {
  748.     case cObjectType:
  749.     case stringType:
  750.     case symbolType:
  751.     case unknownType:
  752.       u.ptrVal = nil;
  753.       pushObj(&u, ptrAlign);
  754.       break;
  755.  
  756.     default:
  757.       badType("UndefinedObject", cType);
  758.     }
  759.   } else if (class == arrayClass) {
  760.     for (i = 1; i <= numOOPs(oopToObj(oop)); i++) {
  761.       pushSmalltalkObj(arrayAt(oop, i), unknownType);
  762.     }
  763.   }
  764.   
  765. }
  766.  
  767. static void pushObj(up, align)
  768. CParamUnion *up;
  769. AlignmentType align;
  770. {
  771.   int i, alignInts;
  772.  
  773.   alignInts = alignments[ENUM_INT(align)] / sizeof(int);
  774.  
  775.   /* Align the stack properly */
  776.   if ((cArg - cArgVec) % alignInts) {
  777.     cArg += alignInts - ((cArg - cArgVec) % alignInts);
  778.   }
  779.   
  780.   for (i = 0; i < typeSizes[ENUM_INT(align)] / sizeof(int); i++) {
  781.     if (cArg - cArgVec >= ARG_VEC_SIZE) {
  782.       errorf("Too many parameters, max = %d.  Extra parameters ignored",
  783.          ARG_VEC_SIZE);
  784.       return;
  785.     }
  786.     *cArg++ = up->valueVec[i];
  787.   }
  788. }
  789.  
  790. static void callCFunction(desc)
  791. CFuncDescriptor desc;
  792. {  
  793.   int        intResult;
  794.   long        longResult;
  795.   double    doubleResult;
  796.   int        (*cFunction)();
  797.   CDataType    returnType;
  798.   OOP        returnTypeOOP;
  799.  
  800.   cFunction = (int (*)())cObjectValue(desc->cFunction);
  801.   if (isInt(desc->returnType)) {
  802.     returnType = (CDataType)toInt(desc->returnType);
  803.     returnTypeOOP = nil;
  804.   } else {
  805.     returnTypeOOP = desc->returnType;
  806.     returnType = cObjectType;
  807.   }
  808.     
  809.   switch (returnType) {
  810.   case voidType:
  811.     (*cFunction)(
  812.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  813.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  814.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  815.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  816.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  817.     break;
  818.   case charType:
  819.   case intType:
  820.     intResult = (*cFunction)(
  821.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  822.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  823.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  824.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  825.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  826.     switch (returnType) {
  827.     case intType: 
  828.       setStackTop(fromInt((long)intResult));
  829.       break;
  830.     case charType:
  831.       setStackTop(charOOPAt((Byte)intResult));
  832.       break;
  833.     }
  834.     break;
  835.  
  836.   case longType:
  837.   case stringType:
  838.   case symbolType:
  839.   case cObjectType:
  840.   case smalltalkType:
  841.     longResult = (*(long (*)())cFunction)(
  842.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  843.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  844.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  845.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  846.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  847.     switch (returnType) {
  848.     case longType:
  849.       setStackTop(fromInt(longResult));
  850.       break;
  851.     case stringType:
  852.       if (longResult == 0) {
  853.     setStackTop(nilOOP);
  854.       } else {
  855.     setStackTop(stringNew((char *)longResult));
  856.       }
  857.       break;
  858.     case symbolType:
  859.       if (longResult == 0) {
  860.     setStackTop(nilOOP);
  861.       } else {
  862.     setStackTop(internString((char *)longResult));
  863.       }
  864.       break;
  865.     case cObjectType:
  866.       if (longResult == 0) {
  867.     setStackTop(nilOOP);
  868.       } else {
  869.     if (returnTypeOOP) {
  870.       setStackTop(cObjectNewTyped((voidPtr)longResult, returnTypeOOP));
  871.     } else {
  872.       setStackTop(cObjectNew((voidPtr)longResult));
  873.     }
  874.       }
  875.       break;
  876.     case smalltalkType:
  877.       setStackTop((OOP)longResult);
  878.       break;
  879.     }
  880.     break;
  881.  
  882.   case doubleType:
  883.     doubleResult = (*(double (*)())cFunction)(
  884.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  885.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  886.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  887.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  888.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  889.     setStackTop(floatNew(doubleResult));
  890.     break;
  891.  
  892.   default:
  893.     errorf("Invalid C function return type specified, index %d\n",
  894.        returnType);
  895.     break;
  896.   }
  897.  
  898.   savedErrno = errno;
  899. }
  900.  
  901. static void badType(smalltalkTypeName, cType)
  902. char    *smalltalkTypeName;
  903. CDataType cType;
  904. {
  905.   errorf("Attempt to pass a %s as a %s", smalltalkTypeName,
  906.      cTypeName[ENUM_INT(cType)]);
  907. }
  908.  
  909.  
  910. OOP makeDescriptor(funcNameOOP, returnTypeOOP, argsOOP)
  911. OOP    funcNameOOP, returnTypeOOP, argsOOP;
  912. {
  913.   char        *funcName;
  914.   void        (*funcAddr)();
  915.   int        numArgs, i;
  916.   CFuncDescriptor desc;
  917.  
  918.   funcName = (char *)toCString(funcNameOOP);
  919.   funcAddr = lookupFunction(funcName);
  920.  
  921.   if (argsOOP == nilOOP) {
  922.     numArgs = 0;
  923.   } else {
  924.     numArgs = numOOPs(oopToObj(argsOOP));
  925.   }
  926.  
  927.   /*
  928.    * since these are all either ints or new objects, I'm not moving the
  929.    * oops
  930.    */
  931.   desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs);
  932.   desc->cFunction = cObjectNew(funcAddr);
  933.   desc->cFunctionName = stringNew(funcName);
  934.   desc->numFixedArgs = fromInt(numArgs);
  935.   desc->returnType = classifyTypeSymbol(returnTypeOOP, true);
  936.   for (i = 1; i <= numArgs; i++) {
  937.     desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i), false);
  938.   }
  939.  
  940.   return (allocOOP(desc));
  941. }
  942.  
  943. static OOP classifyTypeSymbol(symbolOOP, isReturn)
  944. OOP    symbolOOP;
  945. Boolean    isReturn;
  946. {
  947.   SymbolTypeMap    *sp;
  948.   Byte        *symbolName;
  949.  
  950.   for (sp = symbolTypeMap; sp->symbol != nil; sp++) {
  951.     if (*sp->symbol == symbolOOP) {
  952.       return (fromInt(sp->type));
  953.     }
  954.   }
  955.  
  956.   if (isReturn) {
  957.     if (isClass(symbolOOP, cTypeClass)) {
  958.       return (symbolOOP);    /* this is the type we want! */
  959.     }
  960.   }
  961.  
  962.   symbolName = toCString(symbolOOP); /* yeah yeah...but they have the same
  963.                         representation! */
  964.   errorf("Unknown data type symbol: %s", symbolName);
  965.  
  966.   return (fromInt(unknownType));
  967. }
  968.  
  969. /*
  970.  *    void restoreCFuncDescriptor(cFuncDescOOP)
  971.  *
  972.  * Description
  973.  *
  974.  *    This routine is called during image loading to restore a C function
  975.  *    descriptor pointer.  This is because between the time that the image
  976.  *    was made and now, the executable image may have changed, so any
  977.  *    reference to the C function address may be invalid.  We therefore just
  978.  *    perform the function lookup again and use that value.
  979.  *
  980.  * Inputs
  981.  *
  982.  *    cFuncDescOOP: 
  983.  *        A C function descriptor object to be adjusted.  Contains the
  984.  *        name of the function to be looked up.
  985.  *
  986.  */
  987. void restoreCFuncDescriptor(cFuncDescOOP)
  988. OOP    cFuncDescOOP;
  989. {
  990.   CFuncDescriptor desc;
  991.   void        (*funcAddr)();
  992.   char        *funcName;
  993.  
  994.   desc = (CFuncDescriptor)oopToObj(cFuncDescOOP);
  995.   funcName = (char *)toCString(desc->cFunctionName);
  996.   funcAddr = lookupFunction(funcName);
  997.   setCObjectValue(desc->cFunction, funcAddr);
  998. }
  999.  
  1000.  
  1001. /***********************************************************************
  1002.  *
  1003.  *    Call-in support code
  1004.  *
  1005.  ***********************************************************************/
  1006.  
  1007.  
  1008. #ifdef not_working_yet
  1009. send(receiver, selectorStr, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
  1010.      arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17,
  1011.      arg18, arg19, arg20)
  1012. OOP receiver, selector;
  1013. OOP arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
  1014.   arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20;
  1015. {
  1016. }
  1017.  
  1018. OOP newIntObject(i)
  1019. long    i;
  1020. {
  1021.   return (fromInt(i));
  1022. }
  1023.  
  1024. OOP newCharObject(c)
  1025. Byte    c;
  1026. {
  1027.   return (charOOPAt(c));
  1028. }
  1029.  
  1030. OOP newFloatObject(f)
  1031. double    f;
  1032. {
  1033.   OOP        oop;
  1034.  
  1035.   oop = floatNew(f);
  1036.   registerOOP(oop);
  1037.   return (oop);
  1038. }
  1039.  
  1040. ??? Want byte array types ???
  1041.  
  1042. OOP newStringObject(str)
  1043. char    *str;
  1044. {
  1045.   OOP        oop;
  1046.  
  1047.   if (str == nil) {
  1048.     return (nilOOP);
  1049.   } else {
  1050.     oop = stringNew(str);
  1051.     registerOOP(oop);
  1052.     return (oop);
  1053.   }
  1054. }
  1055.  
  1056. OOP newSymbolObject(str)
  1057. char    *str;
  1058. {
  1059.   OOP        oop;
  1060.  
  1061.   if (str == nil) {
  1062.     return (nilOOP);
  1063.   } else {
  1064.     oop = internString(str);
  1065.     return (oop);
  1066.   }
  1067. }
  1068.  
  1069.  
  1070. OOP newCObject(cObject)
  1071. voidPtr    cObject;
  1072. {
  1073.   OOP        oop;
  1074.  
  1075.   if (cObject == nil) {
  1076.     return (nilOOP);
  1077.   } else {
  1078.     oop = cObjectNew(cObject);
  1079.     registerOOP(oop);
  1080.     return (oop);
  1081.   }
  1082. }
  1083.  
  1084. objectType(oop)
  1085. returns the type of an object, an enum, or unknown 
  1086.  
  1087. need back conversion routines
  1088.  
  1089. void freeObject(oop)
  1090. OOP    oop;
  1091. {
  1092.   printf("!!! IMPLEMENT freeObject\n");
  1093. }
  1094.  
  1095.  
  1096. static void registerOOP(oop)
  1097. OOP    oop;
  1098. {
  1099.   printf("!!! IMPLEMENT registerOOP\n");
  1100. }
  1101.  
  1102. #endif /* not_done_yet */
  1103.